#include "sdl.hpp"
#include "sdl-gui.hpp"
#include "main.hpp"

using namespace std;
using namespace sdl;

sdl::Display* display;
sdl::Image* background;
sdl::Image* icon;
sdl::Font* fontTitle;
sdl::Font* font;

// By using inheritance, it is easier to manage the styles of the classes
namespace mygui
{
    class Button : public gui::Button
    {
    public:
        Button(Rect cpos, std::string ctext, gui::Container* parent) : gui::Button(cpos, ctext, parent)
        {
            font = ::font;
            colour = Colour(0, 0, 0);
            background = Color(201, 227, 234);
            hoverBackground = Colour(246, 246, 246);
            drawFrame = false;
        }
    };

    class ServerList : public gui::ListContainer
    {
    public:
        ServerList(Rect cpos, gui::Container* parent) : gui::ListContainer(cpos, NULL, parent)
        {
            font = ::font;
            align = gui::AlignLeft;
            colour = Colour(0, 0, 0);
            background = Colour(246, 246, 246);
            activeBackground = Color(194, 220, 228);
            scrollbar.colour = Color(154, 180, 188);
            scrollbar.background = Color(201, 227, 234);
            scrollbar.max = 0;
            scrollbar.drawFrame = false;
        }

        string getItem(int number)
        {
            return serverList[number].name;
        }

        unsigned int getSize()
        {
            return serverList.size();
        }
    };

    class Title : public gui::Label
    {
    public:
        Title(Rect cpos, std::string ctext, gui::Container* parent = NULL)
        {
            pos = cpos;
            font = ::fontTitle;
            align = gui::AlignLeft;
            colour = Colour(51, 51, 51);
            //background = Color(204, 230, 238);
            text = ctext;
            if (parent != NULL)
                parent->add(this);
        }
    };
}

void optionsMenu()
{
    background->render(display);

    gui::Container* optionsMenu = new gui::Container();

    //                                x    y    w    h      text            parent
    mygui::Title title(         Rect( 25,  25, 750,  30),   "Options");
    mygui::Button btnBack(      Rect( 675, 550, 100,  25),  "Back",         optionsMenu);

    // By using faking pushMouse event, we don't need to wait for user interaction to render the new
    // frame (this is due to SDL_WaitEvent).
    gui::Event e;
    e.saveMouse();
    e.pushMouse();

    title.render();
    SDL_Event event;
    bool running = true;
    while (SDL_WaitEvent(&event) && running && ::running)
    {
        do
        {
            switch (event.type)
            {
            case SDL_QUIT:
                running = false;
                break;
            case SDL_USEREVENT:
            {
                gui::Event gevent(event);
                if (gevent.valid())
                {
                    if (gevent.source() == &btnBack)
                        running = false;
                }
                break;
            }
            default:
                optionsMenu->event(event);
                break;
            }
        }
        while (SDL_PollEvent(&event));

        if (!running || !::running)
            break;
        optionsMenu->render();
        display->update();
    }
    e.pushMouse();
}


void serverSelectMenu()
{
    background->render(display);

    gui::Container* serverSelectMenu = new gui::Container();

    //                                x    y    w    h      text            parent
    mygui::Title title(         Rect( 25,  25, 750,  30),   "Server List");
    //mygui::Button btnSave(      Rect(325, 425, 150,  25),   "Save",         serverSelectMenu);
    //mygui::Button btnAdd(       Rect(475, 425, 150,  25),   "Add Server",   serverSelectMenu);
    mygui::Button btnConnect(   Rect(625, 425, 150,  25),   "Connect",      serverSelectMenu);
    mygui::Button btnBack(      Rect(675, 550, 100,  25),   "Back",         serverSelectMenu);

    //                                        x    y    w    h      parent
    mygui::ServerList   lstServers(     Rect(25, 100, 300, 350),    serverSelectMenu);

    // By using faking pushMouse event, we don't need to wait for user interaction to render the new
    // frame (this is due to SDL_WaitEvent).
    gui::Event e;
    e.saveMouse();
    e.pushMouse();

    title.render();
    SDL_Event event;
    bool running = true;
    while (SDL_WaitEvent(&event) && running && ::running)
    {
        do
        {
            switch (event.type)
            {
            case SDL_QUIT:
                running = false;
                break;
            case SDL_USEREVENT:
            {
                gui::Event gevent(event);
                if (gevent.valid())
                {
                    if (gevent.source() == &btnBack)
                        running = false;
                }
                break;
            }
            default:
                serverSelectMenu->event(event);
                break;
            }
        }
        while (SDL_PollEvent(&event));

        if (!running || !::running)
            break;
        serverSelectMenu->render();
        display->update();
    }
    e.pushMouse();
}

void introMenu()
{
    sdl::Image* logo = new Image(basedir + "logo.png");

    background->render(display);
    logo->render(Rect(160, 255), display);

    gui::Container* introMenu = new gui::Container();

    //                                        x    y    w    h      text            parent
    mygui::Button       btnConnect(     Rect(330, 375, 140,  25),   "Play Online",      introMenu);
    mygui::Button       btnOptions(     Rect(330, 400, 140,  25),   "Options",      introMenu);
    mygui::Button       btnQuit(        Rect(330, 425, 140,  25),   "Quit",         introMenu);

    SDL_Event event;
    while (SDL_WaitEvent(&event) && running)
    {
        do
        {
            switch (event.type)
            {
            case SDL_QUIT:
                running = false;
                break;
            case SDL_USEREVENT:
            {
                gui::Event gevent(event);
                if (gevent.valid())
                {
                    if (gevent.source() == &btnQuit)
                        running = false;
                    if (gevent.source() == &btnOptions)
                    {
                        optionsMenu();
                        display->fill(Rect(0, 0, 800, 600), Color(204, 230, 238));
                        background->render(display);
                        logo->render(Rect(160, 255), display);
                    }
                    if (gevent.source() == &btnConnect)
                    {
                        serverSelectMenu();
                        display->fill(Rect(0, 0, 800, 600), Color(204, 230, 238));
                        background->render(display);
                        logo->render(Rect(160, 255), display);
                    }
                }
                break;
            }
            default:
                introMenu->event(event);
                break;
            }
        }
        while (SDL_PollEvent(&event));

        if (!running)
            break;
        introMenu->render();
        display->update();
    }

    delete logo;
}

void runGUI()
{
    sdl::init();
    display = new Display(800, 600, 32);
    display->title("Checkmate");
    gui::Element::target = display;

    font = new Font(basedir + "liberation-sans.ttf", 13);
    fontTitle = new Font(basedir + "liberation-sans-bold.ttf", 24);

    background = new Image(basedir + "background.png");
    icon = new Image(basedir + "icon.png");
    display->icon(icon);

    introMenu();

    delete background;
    delete icon;
    delete font;
    delete display;
    delete fontTitle;
    sdl::uninit();
}

